Thunk
Thunk是一种临时function, 被当作参数传递进另一个function, 实现function的引用传参,而不是传值传参。
其应用之一如下:
把形如 fs.readFile(fileName, callback);
转化为 Thunk(fileName)(callback)
, 这样就避免了多重嵌套回调, 增加可读性与代码的组织性。
实现原理:1
2
3
4
5var Thunk = function (fileName){
return function (callback){
return fs.readFile(fileName, callback);
};
};
根据此原理,可以将任何函数Thunk化。
把形如 fs.readFile(fileName, callback);
转化为形如 Thunk(fs.readFile)(fileName)(callback)
1
2
3
4
5
6
7
8
9
10
11var Thunk = function(fn){ //fs.readFile
return function (){
var args = Array.prototype.slice.call(arguments); //args [filePathName]
return function (callback){
args.push(callback); //args [filePathName, callback]
return fn.apply(this, args); //this [node执行环境 ?]
}
};
};
Thunk(fs.readFile)(filePathName)(callback);
Generator
Generator 详解
1 | //Generator function标识 function* |
该函数有二种(yield, return
)共三个状态:hello,world和 the end, 用g.next()调用执行并且移动内部指针状态,每调用一次执行一种状态,每次返回一个对象(如下),当执行到return时,状态done为true;
如果该函数没有return语句,则返回的对象的value属性值为undefined
1 | { |
执行时状态1
2
3
4
5
6g.next()
Object {value: "hello", done: false}
g.next()
Object {value: "world", done: false}
g.next()
Object {value: "the end", done: true}
注意: 当next传参数时,会将传的参数当作上一次yield时的返回值, 如下代码可以执行感受下。
1 | function* gen(x) { |
Generator yield语句解析
yield*语句: http://es6.ruanyifeng.com/#docs/generator
Generator 应用
Generator与状态机
1 | //状态机 |
Generator与异步
Generator与Promise
Co 及 Co与Generator的应用
Co function 目的是将形如 fs.readFile(filePath, callback) 的异步方法
转化为形如下面的方法去使用,个人觉得在此种情形下作用与thunk方法类似(但在其它地方还要很多应用):1
2
3
4
5
6
7
8
9
10
11
12// 1.将异步方法重写为如下形(readFile -> readFileCo)
function readFileCo(filePath){
return function(callback){ //这个必须返回这个function且参数为callback
fs.readFile(filePath, callback);
}
}
// 2.使用Co 及 Generator 执行重写后的方法
co(function* (){
yield readFileCo(filePath)
//yield readFileCoFn(filePath);
})(callback); //readfile的callback为 function(error, data){}
结合上面的示例,分析Co的执行原理及Co基本结构如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32//GenFunc 需要传入一个 function*
function co(GenFunc) {
//执行co方法后返回一个方法去执行
return function(cb) {
//执行generator function
var gen = GenFunc()
next();
//next执行(1 times)
//next参数为callback的(err, data)
function next(err, args) {
if (err) {
cb(err);
} else {
//如果有generator next方法
if (gen.next) {
//传参执行generator next,会按序触发yield语句
var ret = gen.next(args)
//如果generator执行状态done为true,则执行回调cb
if (ret.done) {
cb && cb(null, args)
} else {
//如果generator执行状态done不为true
//ret.value是generator执行时yield的返回值, yield返回的是readFileCo(filePath) => 返回的是function(callback), 所以ret.value就是这个function
//而参数next 即为此方法体
//综合来理解,即如果没有done完的话,执行function(callback),此时callback为 next(err, args);
ret.value(next)
}
}
}
}
}
}
ES6 Promise
promise 定义
1 | //Promise 接口表示为一个值的代理,这个值在promise创建时未必已知 |
promise属性
Promise.length
promise方法
Promise.all()
Promise.race()
Promise.reject()
Promise.resolve()
promise原型
Promise.prototype.catch()
Promise.prototype.then()
Generator,Co,Promise相结合
总体来看 Co是为了改造Generator方便去使用,而嵌入Promise则为了更好的去控制异步及相关流程控制。